import java.net.Socket;
import java.util.LinkedList;


public class Game implements Runnable{

	private Player[] player;
	private Enemy[] enemy;
	private LinkedList<EnergyAttack> eAttack;
	private Collidable objects;
	private MapManager mapManager;
	public Game()
	{
		enemy = new Enemy[10];
		mapManager = new MapManager();
		player = new Player[10];
		eAttack = new LinkedList<EnergyAttack>();
	}
	/**
	 * adds a new player to the game.  If the player was already there before, just
	 * reinstates them into the game
	 */
	public void addUser(Socket socket)
	{
		int i = 0;
		boolean found = false;
		while(player.length > i && player[i] != null)
		{
			if(player[i].getSocket().getInetAddress().toString().contentEquals( socket.getInetAddress().toString()))
			{
				if(player[i].getStart() == false)
				{
					player[i].start(socket);
					found = true;
					enemy[i] = new Minion(0);
				}
			}
			i++;
		}
		if(found == false && i < player.length)
		{
			player[i] = new Player(socket);
			player[i].start(socket);
			enemy[i] = new Minion(0);
		}
	}
	/**
	 * There is only one thread for this. It's the main part of the game.
	 * In order it checks for collisions, moves players accordingly, draws the items, and
	 * reads the chat messages
	 */
	public void run() {
		int time = 0;
		while(true)
		{
			if(halfTime())
			{
				String data;
				if(time >=5)
				{
					time = 0;
					
					checkCollisions();
					movePlayers();
					
				}
				data = drawPlayers();
				data = data + drawItems() + readChat();
				data = data + "DARK \n";
				sendData(data);
				player[0].updateSprite();
				time++;
				try {
					Thread.sleep(40);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			else
			{
				String data;
				checkCollisions();
				movePlayers();
				data = drawPlayers();
				data = data + drawItems() + readChat();
				sendData(data);
				try {
					Thread.sleep(40);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public boolean halfTime()
	{
		int i = 0;
		while(i<player.length && player[i] != null)
		{
			if(player[i].getHalfTime())
			{
				return true;
			}
			i++;
		}
		return false;
	}
	/**
	 * checks for any collision, and calls the onCollision method of all objects that have collisions
	 */
	public void checkCollisions()
	{
		int i = 0;
		Collidable[] temp = new Collidable[player.length + enemy.length + eAttack.size()];
		while(i < player.length && player[i] != null)
		{
			temp[i] = player[i];
			i++;
		}
		int j = i;
		i = 0;
		while(i < enemy.length && enemy[i] != null)
		{
			temp[j] = enemy[i];
			i++;
			j++;
		}
		i = 0;
/**		while(i < eAttack.size())
		{
			if(eAttack.get(i) != null)
			{
				temp[j] = eAttack.get(i);
			}
			i++;
			j++;
		}*/
		i = 0;
		while(i<temp.length && temp[i] != null)
		{
			LinkedList<Collidable> ans = mapManager.getCollidable(temp[i].getCurrentPosition());
			if(ans != null && ans.size() >0)
			{
				for(Collidable obj:ans)
				{
					if(obj != null)
					{
						if(temp[i].checkCollision(obj))
						{
							obj.onCollision(temp[i]);
							temp[i].onCollision(obj);
						}
					}
				}
			}
			i++;
		}
	}
	public void moveCharacters()
	{
		movePlayers();
		int i = 0;
		
	}
	public void movePlayers()
	{
		//move players
		
		int i = 0;
		while(i < player.length && player[i] != null)
		{
			if(player[i].getStart())
			{
				player[i].move();
			}
			i++;
		}
		//move enemies
		i = 0;
		while(i < enemy.length)
		{
			if(enemy[i] != null)
			{
				enemy[i].setPlayerList(player);
				enemy[i].update();
				enemy[i].move();
			}
			i++;
		}
		i = 0;
		//add in new attack moves from players
		while(i<player.length && player[i] != null)
		{
			EnergyAttack attack = player[i].getEnergyAttack();
			if(attack != null && eAttack.contains(attack) == false)
			{
				eAttack.add(attack);
			}
			i++;
		}
		i = 0;
		while(i<enemy.length)
		{
			if(enemy[i] != null)
			{
				EnergyAttack attack = enemy[i].getEnergyAttack();
				if(attack != null && eAttack.contains(attack) == false)
				{
					eAttack.add(attack);
				}
			}
			i++;
		}

		//move attacks
		i = 0;
		while(i<eAttack.size())
		{
			if(eAttack.get(i) != null)
			{
				if(eAttack.get(i).isAlive())
				{
					eAttack.get(i).add();
				}
				else
				{
					eAttack.remove(i);
					System.out.println("removed" + i);
				}
			}
			i++;
		}
	}
	public String drawItems()
	{
		String ans = "";
		int i = 0;
		while(i<eAttack.size())
		{
			if(eAttack.get(i) != null)
			{
				ans = ans + eAttack.get(i).getDrawableString();
			}
			else
			{
				eAttack.remove(i);
				System.out.println("removed" + i);
			}
			i++;
		}
		return ans;
	}
	/**
	 * gets all chat messages from players
	 * @return all chat players from players, each with it's own new line starting with "Chat: "
	 */
	public String readChat()
	{
		String str = "";
		int i = 0;
		while(i<player.length && player[i] != null)
		{
			if(player[i].getStart())
			{
				String temp = player[i].readChat();
				if(temp.contentEquals("") == false)
				{
					str = str + "Chat: " + temp + "\n";
				}
			}
			i++;
		}
		return str;
	}
	public void sendData(String data)
	{
		int i = 0;
		while(i<player.length && player[i] !=null)
		{
			if(player[i].getStart())
			{
				player[i].output(data);
			}
			i++;
		}
	}
	public String drawPlayers()
	{
		int i = 0;
		String out = "";
		Character[] temp = new Character[player.length + enemy.length];
		//add all the players
		while(i < player.length && player[i] != null)
		{
			if(player[i].getStart())
			{
				temp[i] = player[i];
			}
			i++;
		}
		//add all the enemies
		int p = 0;
		while(p < enemy.length)
		{
			if(enemy[p] != null)
			{
				temp[i] = enemy[p];
				i++;
			}
			p++;
		}
		i = 0;
		while(i < temp.length && temp[i] != null)
		{
			if(temp[i].characterSet() == true)
			{
					int x = (int)(temp[i].getCurrentPosition().getX());
					String temp0 =  x +"";
					temp0 = paddZeros(temp0,7);
					int y = (int)(temp[i].getCurrentPosition().getY());
					String temp1 = y +"";
					temp1 = paddZeros(temp1,7);
					String temp2 = ((int)Math.toDegrees((temp[i].getCurrentSprite().getAngle()))) + "";
					temp2 = paddZeros(temp2,7);
					String temp3 = temp[i].getCharacterNumber() + "";
					temp3 = paddZeros(temp3,2);
					String temp4 = temp[i].getCurrentSprite().getType() + "";
					temp4 = paddZeros(temp4,2);
					String temp5 = temp[i].getCurrentSprite().getImg() + "";
					temp5 = paddZeros(temp5,1);
					String ans = temp0 + temp1 + temp2 + temp3 + temp4 + temp5;
					out= out + ans + "\n";
			}
			i++;
		}
		return out;
	}
	public String paddZeros(String str,int length)
	{
		String a = str + "";
		if(a.length() > length)
		{
			str = str.substring(0,length);
		}
		while(a.length() < length)
		{
			if(str.charAt(0) == '-')
			{
				String temp = "-0" + a.substring(1);
				a = temp;
			}
			else
			{
				a = "0" + a;
			}
		}
		return a;
	}
}
